<!-- 底图切换组件 -->
<script setup>
import { onMounted, ref, defineProps, nextTick, watch, onBeforeUnmount, computed } from 'vue';
import { useRoute } from 'vue-router';
import { ElTreeSelect } from 'element-plus';
import * as turf from '@turf/turf';
import mapboxgl from 'mapbox-gl';
import Compare from 'mapbox-gl-compare';
import 'mapbox-gl-compare/dist/mapbox-gl-compare.css';
import { BASE_GEOSERVER_URL } from '@/apis';
import { getRelationById } from '@/apis/api-map-server';
import { useMapStore } from '@/stores';
import { GET_MAPBOX_MAP } from '@/utils/map-utils';

mapboxgl.Compare = Compare;

let beforeMap, afterMap, beforeEl;
// const emit = defineEmits(['handleChangeIsBaseLayer']);
// const baseMapName = ref('影像图');
const mapStore = useMapStore();
const route = useRoute();

const props = defineProps({
  mapId: {
    require: true,
    type: String,
  },
});
const mapImgList = ref([]);
const rightSelect = ref('');
const leftSelect = ref('');
const layerList = computed(() => {
  return mapImgList.value.map((item) => item?.children || []).flat(1);
});

const getRelationByIdApi = async () => {
  const [err, data] = await getRelationById({
    menuCode: route.query?.code,
  });

  if (!err) {
    mapImgList.value = data.map((item) => {
      return {
        ...item,
        label: item.serviceName,
        children:
          item?.children?.map((el) => {
            let id = `${item.id}${Math.random()}`;

            return {
              ...el,
              fid: item.id,
              id,
              label: el.layerMeta.name,
              value: id,
              url: `${BASE_GEOSERVER_URL}/st_server_api/service/niktile/?x={x}&y={y}&z={z}&id=${item.id}&lyrname=${el.layerMeta.name}`,
            };
          }) || [],
      };
    });
  }
};

// 2d 3d 切换
function map3dOr2d(now) {
  [beforeMap, afterMap].map((map) => {
    if (now == '3d') {
      map.setProjection('globe');
      map.flyTo({
        pitch: 60,
        zoom: 12,
        bearing: 45,
        speed: 0.5,
      });
      map.setFog({
        color: 'rgba(66, 88, 106, 1.0)',
      });

      // Add some 3D terrain
      map.addSource('mapbox-dem', {
        type: 'raster-dem',
        url: 'mapbox://mapbox.terrain-rgb',
        tileSize: 512,
        maxzoom: 14,
      });
      map.setTerrain({
        source: 'mapbox-dem',
        exaggeration: 2,
      });
      // window.requestAnimationFrame(frame);
    } else {
      if (!map) return;

      if (map.getSource('mapbox-dem')) {
        map.setTerrain();
        map.removeSource('mapbox-dem');
      }

      map.setProjection('mercator');
      map.flyTo({
        pitch: 0,
        zoom: 9,
        bearing: 0,
        speed: 0.5,
      });
    }
  });
}

watch(
  () => mapStore.mode,
  (old, now) => {
    map3dOr2d(now);
    // mapStore.CHANGE_MODE(old);
  },
  {
    deep: true,
    // immediate: true
  },
);

// 初始化卷帘
function initCompare() {
  const map2d = GET_MAPBOX_MAP();
  const center = map2d.getCenter();
  const zoom = map2d.getZoom();
  const bearing_map = map2d.getBearing();
  const pitch = map2d.getPitch();
  const container = document.getElementById('comparison-container');

  beforeMap = map2d;
  afterMap = new mapboxgl.Map({
    container: 'after',
    style: 'mapbox://styles/mapbox/dark-v11',
    center: [center.lng, center.lat],
    zoom: zoom,
    bearing: bearing_map,
    pitch: pitch,
  });

  new mapboxgl.Compare(beforeMap, afterMap, '#comparison-container', {
    // Set this to enable comparing two maps by mouse movement:
    // mousemove: true
  });
  beforeEl = document.getElementById(props.mapId);

  let after = document.getElementById('after');

  // beforeEl.id = 'before'
  container.insertBefore(beforeEl, after);
  nextTick(() => {
    beforeMap?.resize();
  });
  afterMap.on('load', () => {
    map3dOr2d(mapStore.mode);
  });
}

//图层选择
const selectChange = (e, type) => {
  let target = layerList.value.find((el) => el.id == e);

  if (!target) return;

  let map = null;

  switch (type) {
    case 'before':
      leftSelect.value = target.label;
      map = beforeMap;
      break;

    case 'after':
      rightSelect.value = target.label;
      map = afterMap;
      break;

    default:
      break;
  }

  let source = map.getSource('baseVectorSource');

  if (source) {
    map.removeLayer('baseVectorLayer');
    map.removeSource('baseVectorSource');
  }

  map.addSource('baseVectorSource', {
    type: 'raster', // 类型（必填）
    tiles: [
      // 用于指定一个或多个切片数据源的请求地址（可选，和 TileJSON 中的 tiles 属性一致）
      target.url,
    ],
    // "bounds": [-180, -85.051129, 180, 85.051129], // 边界坐标点（可选，用于限定切片的显示范围，默认值为 [-180,-85.051129,180,85.051129]）
    // "scheme": "xyz", // 切片坐标系方案（可选，可选值为 xyz、tms，默认值为 xyz）
    minzoom: 0, // 最小层级（可选，默认值为 0）
    maxzoom: 22, // 最大层级（可选，默认值为 22）
    attribution: '', // 属性信息（可选，用于地图展示时给用户看的一些信息）
  });
  map.addLayer({
    id: 'baseVectorLayer', // 唯一 id （必填）
    type: 'raster', // 类型（必填）
    // "metadata": { // 元数据（可选，用于为 layer 附加任意的属性。为避免冲突，建议添加前缀，如 mapbox:）
    //   "mapbox:name": "test"
    // },
    source: 'baseVectorSource', // 数据源的名称（除了 layer 的 type 为 background 外，source 必填）
    // "source-layer": "clipped", // 数据源的图层（只有数据源 source 的 type 为 vector 时，才能设置 source-layer，其他类型的不可以设置）
    minzoom: 0, // 最小层级（可选，取值范围为 0 ~ 24。当 style 的 zoom 小于此 minzoom 时，layer 将被隐藏）
    maxzoom: 24, // 最大层级（可选，取值范围为 0 ~ 24。当 style 的 zoom 大于此 maxzoom 时，layer 将被隐藏）
    layout: {
      // 布局类属性
      visibility: 'visible', // 可见性（可选，可选值为 none、visible，默认值为 visible）
    },
  });

  const { min_x, min_y, max_x, max_y } = target.layerMeta.boundary_3857;
  let bbox = [
    [min_x, min_y],
    [max_x, max_y],
  ].map((item) => turf.toWgs84(turf.point(item)).geometry.coordinates);

  map.fitBounds(bbox, {
    padding: { top: 10, bottom: 25, left: 15, right: 15 },
  });
};

onMounted(() => {
  getRelationByIdApi();
  nextTick(() => {
    initCompare();
  });
});

onBeforeUnmount(() => {
  let map = GET_MAPBOX_MAP();

  if (!map) return;

  let source = map.getSource('baseVectorSource');

  if (source) {
    map.removeLayer('baseVectorLayer');
    map.removeSource('baseVectorSource');
  }

  beforeEl && document.getElementById('map-root').appendChild(beforeEl);
});
</script>
<template>
  <div id="comparison-container">
    <!-- <div id="before" class="map"></div> -->
    <div id="after" class="map"></div>
    <div class="menu-box">
      <ElTreeSelect v-model="leftSelect" :data="mapImgList" @change="(e) => selectChange(e, 'before')" />
      <ElTreeSelect v-model="rightSelect" :data="mapImgList" @change="(e) => selectChange(e, 'after')" />
    </div>
  </div>
</template>

<style scoped lang="scss">
#comparison-container {
  position: absolute;
  z-index: 1;
  inset: 0;
  // background-color: #fdd;
}

.menu-box {
  position: absolute;
  top: 100px;
  left: 50%;
  display: flex;
  gap: 20px;
  width: 600px;
  height: 200px;
  transform: translateX(-50%);
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;

  :deep(.el-tree) {
    background-color: #fff2;
  }
}

:deep(.mapboxgl-compare) {
  position: absolute;
  top: 0;

  .compare-swiper-vertical {
    background-position: center;
  }
}

.map {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
}
</style>
